﻿#pragma once

#include <learn/alg/alg_dynamic_surface.h>
#include <learn/alg/alg_geom.h>
#include <learn/alg/alg_pia_surface.h>
#include <learn/geom/geom_bspline_curve.h>
#include <learn/geom/geom_bspline_surface.h>
#include <learn/math/integrator.h>

namespace xi
{

namespace alg
{

using namespace xi::geom;

struct EXT_SYMBOL Alg_Covering
{
    virtual std::shared_ptr<Geom_BSplineSurface<3>> cover(
        std::vector<std::shared_ptr<Geom_BSplineCurve<3>>> &&curves) = 0;
};

struct EXT_SYMBOL Alg_Coons_Covering : Alg_Covering
{
    /**
     * @brief 使用 Coons 曲面覆盖 2-4 条边界曲线
     *
     * @param[in] curves
     * @return std::shared_ptr<Geom_BSplineSurface<3>>
     */
    std::shared_ptr<Geom_BSplineSurface<3>> cover(std::vector<std::shared_ptr<Geom_BSplineCurve<3>>> &&curves) override;
};

struct EXT_SYMBOL Alg_FairingEnergy_Covering : Alg_Covering
{
    std::size_t boundarySampleNum = 1000; // 采样数
    std::size_t uDegree = 3, vDegree = 3;
    std::size_t uPoleNum = 36, vPoleNum = 36;
    double wStretch = 0.3 * 1e-8, wBending = 0.7 * 1e-8;
    std::vector<Vec2> params; // 多于 4 边时保存参数值
    std::vector<Vec3> data;   // 多于 4 边时保存数据值

    /**
     * @brief 使用最小化能量法覆盖 2-4 边界曲线
     *
     * @param[in] curves
     * @return std::shared_ptr<Geom_BSplineSurface<3>>
     */
    std::shared_ptr<Geom_BSplineSurface<3>> cover(std::vector<std::shared_ptr<Geom_BSplineCurve<3>>> &&curves) override;
};

struct EXT_SYMBOL Alg_FairingPIA_Covering : Alg_Covering
{
    std::size_t boundarySampleNum = 1000; // 采样数
    std::size_t iterNum = 1000;           // 迭代次数
    std::size_t uDegree = 3, vDegree = 3;
    std::size_t uPoleNum = 9, vPoleNum = 9; // 初始网格规模
    double wStretchBoundary = 0.0 * 1e-16, wBendingBoundary = 0.7 * 1e-16;
    double wStretchInterior = 0.0, wBendingInterior = 1.0 * 1e-1;
    std::vector<Vec2> params; // 多于 4 边时保存参数值
    std::vector<Vec3> data;   // 多于 4 边时保存数据值

    /**
     * @brief 使用 Fairing-PIA 算法覆盖边界曲线
     *
     * @param[in] curves
     * @return std::shared_ptr<Geom_BSplineSurface<3>>
     */
    std::shared_ptr<Geom_BSplineSurface<3>> cover(std::vector<std::shared_ptr<Geom_BSplineCurve<3>>> &&curves) override;
};

} // namespace alg

} // namespace xi
